home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / sipp / srgp / src / x / srgp_inp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-11  |  15.4 KB  |  521 lines

  1. #include "HEADERS.h"
  2. #include "srgplocal.h"
  3. #include <ctype.h>
  4. #include <X11/keysym.h>
  5.  
  6. /** LOW-LEVEL "DRIVERS"
  7.  
  8.    SRGP__activateDevice (deviceID)
  9.       Must be called when device is going from INACTIVE to active, OR
  10.          when device is changed from one active mode to the other.
  11.  
  12.    SRGP__deactivateDevice (deviceID)
  13.       Must be called only when device is going from active to inactive.
  14.  
  15.  
  16.    SRGP__handleRawEvents (boolean in_waitEvent_call)
  17.       This function nevers enters a wait state.
  18.       It examines all the events on the "raw"
  19.          queue: the queue of the underlying graphics package
  20.      (e.g., X11, Mac).
  21.       Exception: it may not handle all the raw events.
  22.          It exits as soon as it sees a valid trigger situation.
  23.       It returns a device ID IF AND ONLY IF...
  24.      1) the appl. is in a call to SRGP_waitEvent(), AND
  25.      2) a valid trigger for a device currently in Event mode
  26.         has been encountered.
  27.       IF it does return a device ID, THEN...
  28.          It automatically sets the proper value for either
  29.          srgp__get_locator_measure or
  30.          srgp__get_keyboard_measure
  31.      in preparation for the application's ensuing call to 
  32.          SRGP_get...()
  33.       Another exception: it may "pass over" some raw events and
  34.          just leave them in the raw queue.
  35.       It will pass over a raw event IF AND ONLY IF...
  36.      1) the appl. is not in a call to SRGP_waitEvent(), AND
  37.      2) the event is a valid trigger for a device
  38.         currently in Event mode.
  39.       Another possibility is that it will discard a raw event
  40.          without processing it at all.
  41.       It will discard a raw event IF AND ONLY IF...
  42.          The event is for a device that is currently inactive.
  43. **/
  44.  
  45. #define BACKSPACE_KEY     127
  46. #define CARRIAGE_RETURN  13
  47.  
  48. #define KEYS        (KeyPressMask)
  49. #define MOTION_HINT    (PointerMotionHintMask|PointerMotionMask)
  50. #define MOTION_ALL    (PointerMotionMask)
  51. #define BUTTONS (ButtonPressMask|ButtonReleaseMask|OwnerGrabButtonMask)
  52.  
  53. /* pausch hack: added ExposureMask */
  54. #define DEFAULT    (StructureNotifyMask|EnterWindowMask|ExposureMask)
  55.  
  56. /** X SELECT INPUT MASKS
  57.   I am always looking for keyboard presses (X events) because
  58.   some keys are always active, allowing the user to press F6
  59.   (for example) to turn on tracing at run-time, etc.
  60.   
  61.   When the locator is in sample mode w/o rubber echo, I need
  62.       pointer-motion *hints* only.
  63.   When the locator is using rubber echo, I need all pointer motion events.
  64.   When the locator is in event mode and not echoed rubberly,
  65.       I only need button-event reports.
  66. **/
  67.  
  68. static unsigned long 
  69. selectinputmask 
  70.  [3] /*inputMode*/
  71.  [2] /*boolean:rubberon?*/ = {
  72.    /* input mode: INACTIVE */   {0L, 0L},
  73.    /* input mode: SAMPLE */       {MOTION_ALL|BUTTONS, MOTION_ALL|BUTTONS},
  74.    /* input mode: EVENT */       {BUTTONS, MOTION_ALL|BUTTONS}
  75. };
  76.  
  77. #define SelectInput(LOCMODE,RUBBERON)   \
  78.    XSelectInput (srgpx__display, srgpx__screenwin, \
  79.          selectinputmask[LOCMODE][RUBBERON?1:0]|KEYS|DEFAULT)
  80.  
  81.  
  82. void
  83. SRGP__initInputDrivers()
  84. {
  85.    /* INITIALIZE X INPUT */
  86.    SelectInput (INACTIVE,FALSE);
  87. }
  88.  
  89.  
  90.  
  91. void
  92. SRGP__updateInputSelectionMask()
  93. {
  94.    SelectInput (srgp__cur_mode[LOCATOR], 
  95.         srgp__cur_locator_echo_type > CURSOR);
  96. }
  97.  
  98.  
  99.  
  100.  
  101. /** RAW-LEVEL DEACTIVATION OF A DEVICE
  102. Responsible for erasing echo, and resetting device's measure to the
  103.    hardwired default.
  104. Upon entry, the device's cur_mode is its old value (has not been
  105.    changed yet)!  And this procedure does not change it!
  106. **/
  107.  
  108. void
  109. SRGP__deactivateDevice (int device)
  110. {
  111.    XEvent xev;
  112.  
  113.    switch (device) {
  114.       
  115.     case LOCATOR:
  116.       SRGP__disableLocatorRubberEcho();
  117.       SRGP__disableLocatorCursorEcho();
  118.       srgp__cur_locator_measure.position = 
  119.          SRGP_defPoint(srgp__canvasTable[0].max_xcoord>>1,
  120.                srgp__canvasTable[0].max_ycoord>>1);
  121.       SelectInput(INACTIVE,FALSE);
  122.       /* Delete all currently queued locator-related raw events. */
  123.       while (XCheckMaskEvent(srgpx__display, MOTION_ALL|BUTTONS, &xev));
  124.       break;
  125.        
  126.     case KEYBOARD:
  127.       SRGP__disableKeyboardEcho();
  128.       srgp__cur_keyboard_measure.buffer[0] = '\0';
  129.       bzero (srgp__cur_keyboard_measure.modifier_chord,
  130.          sizeof(srgp__cur_keyboard_measure.modifier_chord));
  131.       break;
  132.    }
  133. }
  134.  
  135.  
  136.  
  137.  
  138.  
  139. /** RAW-LEVEL ACTIVATION OF A DEVICE
  140. Called whenever:
  141.   a device is placed into EVENT or SAMPLE mode...
  142.      a) when previously inactive
  143.      b) when previously active but in a different mode
  144. Responsible for initiating echo and setting X's selection mask.
  145. Upon entry, the device's echo info and mode has already been set
  146.   to their new values.
  147. **/
  148.  
  149. void
  150. SRGP__activateDevice (int device)
  151. {
  152.    switch (device) {
  153.     case LOCATOR:
  154.       SRGP__disableLocatorCursorEcho();
  155.       SRGP__disableLocatorRubberEcho();
  156.       SRGP__enableLocatorCursorEcho();
  157.       SRGP__enableLocatorRubberEcho();
  158.       SRGP__updateInputSelectionMask();
  159.       break;
  160.        
  161.     case KEYBOARD:
  162.       SRGP__enableKeyboardEcho();
  163.       break;
  164.    }
  165. }
  166.  
  167.  
  168.  
  169.  
  170.  
  171. void
  172. SRGP__updateRawCursorPosition ()
  173. {
  174.    srgp__cur_Xcursor_x = srgp__cur_locator_measure.position.x;
  175.    srgp__cur_Xcursor_y = 
  176.       SCREENFIXED(srgp__cur_locator_measure.position.y);
  177.    XWarpPointer
  178.       (srgpx__display,
  179.        None, srgpx__screenwin,
  180.        0,0,0,0,
  181.        srgp__cur_Xcursor_x, srgp__cur_Xcursor_y);
  182.    SRGP__updateLocatorRubberEcho();
  183. }
  184.  
  185.  
  186.  
  187.  
  188. static   XEvent xevent;
  189. static   int xstrcount;
  190. static   char buffer[50];
  191. static   KeySym keysym;
  192. static   unsigned long mask;
  193. static   boolean in_wait_event;
  194.  
  195.  
  196.  
  197. void
  198. SRGP__updateLocationKnowledge ()
  199. {
  200.    Window rw, cw;
  201.    int xr, yr;
  202.    unsigned int keys_buttons;
  203.  
  204.    XQueryPointer (srgpx__display, srgpx__screenwin,
  205.           &rw, &cw, &xr, &yr,
  206.           &srgp__cur_Xcursor_x, &srgp__cur_Xcursor_y, 
  207.           &keys_buttons);
  208.    srgp__cur_locator_measure.position.x = srgp__cur_Xcursor_x;
  209.    srgp__cur_locator_measure.position.y = SCREENFIXED(srgp__cur_Xcursor_y);
  210.    
  211.    srgp__dirty_location = FALSE;
  212. }
  213.  
  214.  
  215.  
  216.  
  217. static inputDevice HandleXButtonEvent (buttonStatus TRANSITION_TYPE) 
  218. {
  219.    int which_button;
  220.    boolean do_return_event_notice = FALSE;
  221.  
  222.  
  223.    which_button = xevent.xbutton.button - 1;
  224.  
  225.    if (srgp__cur_mode[LOCATOR] != EVENT)
  226.       goto change_cur_measure;
  227.  
  228.    if (((srgp__cur_locator_button_mask >> which_button) & 1) == 0)
  229.       goto change_cur_measure;
  230.  
  231.    if ( ! in_wait_event) {
  232.       XPutBackEvent (srgpx__display, &xevent);
  233.       mask &=  ~(BUTTONS);
  234.       return NO_DEVICE;
  235.    }
  236.  
  237.    do_return_event_notice = TRUE;
  238.  
  239.  change_cur_measure:
  240.    srgpx__cur_time = xevent.xbutton.time;
  241.    srgp__cur_locator_measure.button_chord[which_button] = TRANSITION_TYPE;
  242.    srgp__cur_locator_measure.button_of_last_transition = which_button;
  243.    srgp__cur_locator_measure.modifier_chord[SHIFT] =
  244.       (xevent.xbutton.state&ShiftMask?TRUE:FALSE); 
  245.    srgp__cur_locator_measure.modifier_chord[CONTROL] =  
  246.       (xevent.xbutton.state&ControlMask?TRUE:FALSE); 
  247.    srgp__cur_locator_measure.modifier_chord[META] =  
  248.       (xevent.xbutton.state&Mod1Mask?TRUE:FALSE); 
  249.    srgp__cur_locator_measure.position.x = 
  250.       xevent.xbutton.x; 
  251.    srgp__cur_locator_measure.position.y = 
  252.       srgp__canvasTable[0].max_ycoord - xevent.xbutton.y; 
  253.    if (do_return_event_notice) {
  254.       srgp__get_locator_measure = srgp__cur_locator_measure; 
  255.       return LOCATOR; 
  256.    }
  257.    return NO_DEVICE;
  258. }
  259.  
  260.  
  261.  
  262. static inputDevice HandleRawModeKeyEvent (void)
  263. {
  264.    boolean do_return_event_notice = FALSE;
  265.    
  266.    if (srgp__cur_mode[KEYBOARD] != EVENT)
  267.       goto change_cur_measure;
  268.    
  269.    if ( ! in_wait_event) {
  270.       XPutBackEvent (srgpx__display, &xevent);
  271.       mask &=  ~(KEYS);
  272.       return NO_DEVICE;
  273.    }
  274.  
  275.    do_return_event_notice = TRUE;
  276.    
  277.  change_cur_measure:
  278.    srgp__cur_keyboard_measure.buffer[0] = *buffer;
  279.    srgp__cur_keyboard_measure.buffer[1] = '\0';
  280.    srgp__cur_keyboard_measure.modifier_chord[SHIFT] =
  281.       (xevent.xkey.state&ShiftMask?TRUE:FALSE);
  282.    srgp__cur_keyboard_measure.modifier_chord[CONTROL] =
  283.       (xevent.xkey.state&ControlMask?TRUE:FALSE);
  284.    srgp__cur_keyboard_measure.modifier_chord[META] =
  285.       (xevent.xkey.state&Mod1Mask?TRUE:FALSE);
  286.    if (do_return_event_notice) {
  287.       strcpy (srgp__get_keyboard_measure.buffer, 
  288.           srgp__cur_keyboard_measure.buffer);
  289.       bcopy (srgp__cur_keyboard_measure.modifier_chord,
  290.          srgp__get_keyboard_measure.modifier_chord,
  291.          sizeof(srgp__get_keyboard_measure.modifier_chord));
  292.       srgp__get_keyboard_measure.position =
  293.      srgp__cur_keyboard_measure.position;
  294.       return KEYBOARD;
  295.    }
  296.    return NO_DEVICE;
  297. }
  298.  
  299.  
  300. static inputDevice HandleProcModeKeyEvent (void)
  301. {
  302.    boolean do_return_event_notice = FALSE;
  303.    
  304.    switch (buffer[0]) {
  305.     case CARRIAGE_RETURN:
  306.       if (srgp__cur_mode[KEYBOARD] != EVENT)
  307.      goto erase_cur_measure;
  308.       if (in_wait_event)
  309.      do_return_event_notice = TRUE;
  310.       else {
  311.      XPutBackEvent (srgpx__display, &xevent);
  312.      mask &=  ~KEYS;
  313.      return NO_DEVICE;
  314.       }
  315.       if (do_return_event_notice) {
  316.      strcpy (srgp__get_keyboard_measure.buffer, 
  317.          srgp__cur_keyboard_measure.buffer);
  318.      srgp__get_keyboard_measure.position =
  319.         srgp__cur_keyboard_measure.position;
  320.       }
  321.     erase_cur_measure:
  322.       srgp__cur_keyboard_measure.buffer[0] = '\0';
  323.       srgp__cur_keyboard_measure_length = 0;
  324.       SRGP__updateKeyboardEcho();
  325.       if (do_return_event_notice)
  326.      return KEYBOARD;
  327.       break;
  328.       
  329.     case BACKSPACE_KEY:
  330.       if (srgp__cur_keyboard_measure_length > 0) {
  331.      srgp__cur_keyboard_measure_length =
  332.         srgp__cur_keyboard_measure_length - 1;
  333.      srgp__cur_keyboard_measure.buffer
  334.         [srgp__cur_keyboard_measure_length] =
  335.            '\0';
  336.      SRGP__updateKeyboardEcho();
  337.       }
  338.       break;
  339.       
  340.     default:
  341.       /* CHECK: IS THE KEY PRINTABLE ASCII? */
  342.       if ((isprint(*buffer)) &&
  343.       (srgp__cur_keyboard_measure_length < MAX_STRING_SIZE)) {
  344.      srgp__cur_keyboard_measure.buffer
  345.         [srgp__cur_keyboard_measure_length] = 
  346.            *buffer;
  347.      srgp__cur_keyboard_measure_length++;
  348.      srgp__cur_keyboard_measure.buffer
  349.         [srgp__cur_keyboard_measure_length] = 
  350.            '\0';
  351.      SRGP__updateKeyboardEcho();
  352.       }
  353.       break;
  354.    }
  355.    return NO_DEVICE;
  356. }
  357.    
  358.  
  359.  
  360.  
  361.  
  362.  
  363. /** SRGP__handleRawEvents
  364.       This function nevers enters a wait state, unless it has been
  365.          called as a result of SRGP_waitEvent(FOREVER).
  366.       It examines all the events on the "raw"
  367.          queue: the queue of the underlying graphics package
  368.      (e.g., X11, Mac).
  369.       Exception: it may not handle all the raw events.
  370.          It exits as soon as it sees a valid trigger situation.
  371.       It returns a device ID IF AND ONLY IF...
  372.      1) the appl. is in a call to SRGP_waitEvent(), AND
  373.      2) a valid trigger for a device currently in Event mode
  374.         has been encountered.
  375.       IF it does return a device ID, THEN...
  376.          It automatically sets the proper value for either
  377.          srgp__get_locator_measure or
  378.          srgp__get_keyboard_measure
  379.      in preparation for the application's ensuing call to 
  380.          SRGP_get...()
  381.       Another exception: it may "pass over" some raw events and
  382.          just leave them in the raw queue.
  383.       It will pass over a raw event IF AND ONLY IF...
  384.      1) the appl. is not in a call to SRGP_waitEvent(), AND
  385.      2) the event is a valid trigger for a device
  386.         currently in Event mode.
  387.       Another possibility is that it will discard a raw event
  388.          without processing it at all.
  389.       It will discard a raw event IF AND ONLY IF...
  390.          The event is for a device that is currently inactive.
  391. **/
  392.  
  393. int
  394.    SRGP__handleRawEvents (boolean inwaitevent, boolean forever)
  395. {
  396.    inputDevice id;
  397.    XEvent   unusedXEvent; /* pausch hack; used to flush expose events */   
  398.    in_wait_event = inwaitevent;
  399.  
  400.    mask = (KEYS|MOTION_ALL|DEFAULT|BUTTONS);
  401.  
  402.    /* pausch hack: we need to do this to get the exposure events */
  403.    XSelectInput(srgpx__display, srgpx__screenwin, mask);
  404.  
  405.  
  406.    while (1) {
  407.       
  408.       if (forever && inwaitevent) {
  409.          XMaskEvent (srgpx__display, mask, &xevent);
  410.       }
  411.       else {
  412.          if ( ! XCheckMaskEvent (srgpx__display, mask, &xevent))
  413.      {
  414.         return NO_DEVICE;
  415.     }
  416.       }
  417.       
  418.       switch (xevent.type) {
  419.      
  420.        case EnterNotify:
  421.      /* IF ON COLOR SYSTEM:
  422.         When cursor enters screen canvas, install SRGP colormap. */
  423.      if ((srgp__available_depth > 1) && 
  424.          (srgp__available_depth == srgp__application_depth))
  425.         XInstallColormap (srgpx__display, srgpx__colormap);
  426.      break;
  427.      
  428.        case MotionNotify:
  429.      /* WE CAN ASSUME LOCATOR IS ACTIVE IF WE GET HERE. */
  430.      srgpx__cur_time = xevent.xmotion.time;
  431.      if (xevent.xmotion.is_hint)
  432.         /* WE CAN ASSUME RUBBER-ECHO IS OFF IF WE GET HERE. */
  433.         /* WE CAN ALSO ASSUME LOCATOR IS IN SAMPLE MODE IF WE GET HERE. */
  434.         srgp__dirty_location = TRUE;
  435.      else {
  436.         srgp__cur_Xcursor_x = xevent.xmotion.x;
  437.         srgp__cur_Xcursor_y = xevent.xmotion.y;
  438.         srgp__cur_locator_measure.position.x = srgp__cur_Xcursor_x;
  439.         srgp__cur_locator_measure.position.y = 
  440.            SCREENFIXED(srgp__cur_Xcursor_y);
  441.         SRGP__updateLocatorRubberEcho();
  442.      }
  443.      break;
  444.      
  445.        case ButtonPress:
  446.      if (id = HandleXButtonEvent (DOWN)) {
  447.         return id;
  448.      }
  449.      break;
  450.      
  451.        case ButtonRelease:
  452.      if (id = HandleXButtonEvent (UP)) {
  453.         return id;
  454.      }
  455.      break;
  456.      
  457.        case MappingNotify:
  458.      XRefreshKeyboardMapping (&xevent.xmapping);
  459.      break;
  460.      
  461.        case Expose:
  462.      /* a pausch hack: argubly, we really should have a separate 'expose'
  463.         SRGP callback to the application, but we're just going to
  464.         assume that he'll do a complete repaint when he's resized
  465.         */
  466.  
  467.      SRGP__reactToScreenResize(srgp__canvasTable[0].max_xcoord+1,
  468.                    srgp__canvasTable[0].max_ycoord+1);
  469.  
  470.      break;
  471.  
  472.        case ConfigureNotify:
  473.      /* WE ONLY WISH TO REACT IF TRULY INVOLVED RESIZING (not just move) */
  474.      if (xevent.xconfigure.width == srgp__canvasTable[0].max_xcoord+1) 
  475.         if (xevent.xconfigure.height == srgp__canvasTable[0].max_ycoord+1) 
  476.            break;
  477.      
  478.      /* IF WE GET HERE, we wish to change the dimensions as recorded in
  479.         the canvas table, being careful if the screen canvas is currently
  480.         active. */
  481.      SRGP__reactToScreenResize
  482.         (xevent.xconfigure.width, xevent.xconfigure.height);
  483.      /* at this point, any exposes are unnecessary, so flush them */
  484.      while ( XCheckTypedEvent(srgpx__display, Expose, &unusedXEvent));
  485.      break;
  486.      
  487.        case KeyPress:
  488.      xstrcount = XLookupString (&xevent.xkey, buffer, 50, &keysym, 0);
  489.      /* HERE, CHECK FOR keysym==FKEY for interesting FKEYS. */
  490.  
  491.      /* Rob hack for arrow keys */
  492.      switch (keysym) {
  493.        case XK_Up:        xstrcount = 1;    buffer[0] = 16;    buffer[1] = '\0';    break;
  494.        case XK_Down:    xstrcount = 1;    buffer[0] = 14;    buffer[1] = '\0';    break;
  495.        case XK_Left:    xstrcount = 1;    buffer[0] = 2;    buffer[1] = '\0';    break;
  496.        case XK_Right:    xstrcount = 1;    buffer[0] = 6;    buffer[1] = '\0';    break;
  497.      }
  498.  
  499.      if (srgp__cur_mode[KEYBOARD] == INACTIVE) 
  500.         break;
  501.      if (xstrcount != 1)
  502.         break;
  503.      
  504.      srgpx__cur_time = xevent.xkey.time;
  505.      srgp__cur_keyboard_measure.position.x = xevent.xkey.x;
  506.      srgp__cur_keyboard_measure.position.y = SCREENFIXED(xevent.xkey.y);
  507.      
  508.      if (srgp__cur_keyboard_processing_mode == RAW) {
  509.         if (id = HandleRawModeKeyEvent()) {
  510.            return id;
  511.         }
  512.      }
  513.      else {
  514.         if (id = HandleProcModeKeyEvent()) {
  515.            return id;
  516.         }
  517.      }
  518.       }
  519.    }
  520. }
  521.